package ocean.chinacraft.common.tileentity.function;

import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.NonNullList;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import ocean.chinacraft.common.ModItems;
import ocean.chinacraft.common.constants.Constants;
import ocean.chinacraft.common.world.item.ModSilkWorm;
import ocean.chinacraft.common.ModTileEntity;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * 养蚕架Tile
 *
 * @author zhang
 * @since 2021/11/5
 */
public class SericultureFrameBlockTile extends TileEntity implements ITickableTileEntity, IInventory {

    public final ItemStackHandler itemHandler = createHandler();

    private final LazyOptional<IItemHandler> handler = LazyOptional.of(() -> itemHandler);

    protected NonNullList<ItemStack> items = NonNullList.withSize(11, ItemStack.EMPTY);

    private ItemStackHandler createHandler() {
        return new ItemStackHandler(11) {
            @Override
            protected void onContentsChanged(int slot) {
                SericultureFrameBlockTile.super.setChanged();
            }

            @Override
            public boolean isItemValid(int slot, @Nonnull ItemStack stack) {
                if (slot < 9) {
                    return stack.getItem() instanceof ModSilkWorm;
                } else if (slot == 9) {
                    return stack.getItem() == ModItems.MULBERRY_LEAF.get();
                } else if (slot == 10) {
                    return stack.getItem() == ModItems.SILKWORM_CHRYSALIS.get();
                }
                return false;
            }

            @Override
            public int getSlotLimit(int slot) {
                if (slot < 9) {
                    return 1;
                }
                return 64;
            }

            @Nonnull
            @Override
            public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {
                if (!isItemValid(slot, stack)) {
                    return stack;
                }
                return super.insertItem(slot, stack, simulate);
            }
        };
    }

    @Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
        if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            return handler.cast();
        }
        return super.getCapability(cap, side);
    }

    @Override
    public void load(@Nonnull BlockState state, @Nonnull CompoundNBT nbt) {
        itemHandler.deserializeNBT(nbt.getCompound("SericultureFrame"));
        super.load(state, nbt);
    }

    @Nonnull
    @Override
    public CompoundNBT save(@Nonnull CompoundNBT nbt) {
        nbt.put("SericultureFrame", itemHandler.serializeNBT());
        return super.save(nbt);
    }

    @Override
    public void tick() {
        if (level != null && !level.isClientSide()) {
            run();
        }
    }

    public SericultureFrameBlockTile(TileEntityType<?> entityType) {
        super(entityType);
    }

    public SericultureFrameBlockTile() {
        this(ModTileEntity.SERICULTURE_FRAME_BLOCK_TILE.get());
    }

    @Override
    public int getContainerSize() {
        return 11;
    }

    @Override
    public boolean isEmpty() {
        return items.isEmpty();
    }

    @Override
    public ItemStack getItem(int index) {
        return items.get(index);
    }

    @Override
    public ItemStack removeItem(int index1, int index2) {
        return ItemStackHelper.removeItem(this.items, index1, index2);
    }

    @Override
    public ItemStack removeItemNoUpdate(int index) {
        return ItemStackHelper.takeItem(this.items, index);
    }

    @Override
    public void setItem(int index, ItemStack itemStack) {
        this.items.set(index, itemStack);
        if (itemStack.getCount() > this.getMaxStackSize()) {
            itemStack.setCount(this.getMaxStackSize());
        }
    }

    @Override
    public boolean stillValid(PlayerEntity player) {
        if (level != null) {
            if (level.getBlockEntity(this.worldPosition) != this) {
                return false;
            } else {
                return player.distanceToSqr((double) this.worldPosition.getX() + 0.5D,
                        (double) this.worldPosition.getY() + 0.5D, (double) this.worldPosition.getZ() + 0.5D) <= 64.0D;
            }
        }
        return false;
    }

    @Override
    public void clearContent() {
        items.clear();
    }

    private void run() {
        Inventory inv = new Inventory(itemHandler.getSlots());
        for (int i = 0; i < itemHandler.getSlots(); i++) {
            ItemStack stack = itemHandler.getStackInSlot(i);
            inv.setItem(i, stack);
            if (!stack.isEmpty()) {
                items.set(i, stack);
            }
        }
        work();
    }

    public void work() {
        if (level != null && !level.isClientSide) {
            for (int i = 0; i < 9; i++) {
                ItemStack stack = getStackInSlot(i);
                //是蚕
                if (stack.getItem() instanceof ModSilkWorm && stack.getItem() != ModItems.DEAD_SILKWORM.get()) {
                    if (stack.getTag() != null) {
                        // 对于蚕卵、蚕
                        //TODO 蚕茧
                        CompoundNBT nbt = stack.getTag();
                        int schedule = nbt.getInt(Constants.SILK_WORM_CYCLE);
                        // 当蚕在当前阶段演化完，正准备进入下一阶段
                        if (schedule >= ModSilkWorm.LIFE_CYCLE[nbt.getInt(Constants.SILK_WORM_LEVEL)]) {
                            if (nbt.getInt(Constants.SILK_WORM_LEVEL) == 2) {
                                if (getStackInSlot(10).isEmpty()) {
                                    itemHandler.extractItem(i, 1, false);
                                    itemHandler.insertItem(10, new ItemStack(ModItems.SILKWORM_CHRYSALIS.get()), false);
                                } else {
                                    ItemStack slotStack = getStackInSlot(10);
                                    if (slotStack.getCount() < 64) {
                                        itemHandler.extractItem(i, 1, false);
                                        slotStack.grow(1);  // 将现有堆叠数量加一
                                    }
                                }
                            } else {
                                ItemStack youngSilkStack = new ItemStack(ModItems.YOUNG_SILKWORM.get());
                                itemHandler.extractItem(i, 1, false);
                                itemHandler.insertItem(i, youngSilkStack, false);
                                nbt.putInt(Constants.SILK_WORM_CYCLE, 0);
                                nbt.putInt(Constants.SILK_WORM_LEVEL,
                                        nbt.getInt(Constants.SILK_WORM_LEVEL) + 1);
                                youngSilkStack.setTag(nbt);
                            }
                        } else {
                            //是否是幼蚕阶段
                            if (nbt.getInt(Constants.SILK_WORM_LEVEL) == 1) {
                                //没有桑叶，停止生长
                                if (getStackInSlot(9).isEmpty()) {
                                    continue;
                                }
                                if (level.isRaining() && level.canSeeSky(getTileEntity().getBlockPos())) {
                                    //蚕有几率死亡
                                    if (level.random.nextInt(getSilkWornDeathProbability()) <= 30) {
                                        itemHandler.extractItem(i, 1, false);
                                        itemHandler.insertItem(i, new ItemStack(ModItems.DEAD_SILKWORM.get()),
                                                false);
                                    }
                                    continue;
                                }
                                //蚕有几率吃掉桑叶
                                if (level.random.nextInt(getLeafEat()) <= 5) {
                                    itemHandler.extractItem(9, 1, false);
                                }
                            }
                            //不是幼蚕阶段继续成长
                            nbt.putInt(Constants.SILK_WORM_CYCLE, schedule + 1);
                        }
                        stack.setTag(nbt);
                        //TODO 对于飞蛾,遍历物品槽找到异性后直接产生后代蚕卵
                    } else {
                        //设置默认NBT
                        CompoundNBT nbt = new CompoundNBT();
                        nbt.putInt(Constants.SILK_WORM_CYCLE, 0);
                        nbt.putInt(Constants.SILK_WORM_LEVEL, 0);
                        stack.setTag(nbt);
                    }
                }
                //不是蚕
            }
        }
    }

    private ItemStack getStackInSlot(int slot) {
        return itemHandler.getStackInSlot(slot);
    }

    public int getSilkWornDeathProbability() {
        return 100;
    }

    public int getLeafEat() {
        return 100;
    }
}
